package com.tanhua.app.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tanhua.api.*;
import com.tanhua.app.interceptor.UserHolder;
import com.tanhua.commons.utils.Constants;
import com.tanhua.config.template.HuanXinTemplate;
import com.tanhua.model.dto.RecommendUserDto;
import com.tanhua.model.mongo.RecommendUser;
import com.tanhua.model.mongo.UserLike;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.pojo.Question;
import com.tanhua.model.pojo.User;
import com.tanhua.model.pojo.UserInfo;
import com.tanhua.model.vo.NearUserVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.TodayBest;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class TanhuaService {

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @DubboReference
    private RecommendUserApi recommendUserApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private QuestionApi questionApi;

    @DubboReference
    private UserLikeApi userLikeApi;

    @DubboReference
    private FriendApi friendApi;

    @DubboReference
    private UserLocationApi userLocationApi;

    @DubboReference
    private VisitorsApi visitorsApi;

    //查询今日佳人
    public TodayBest todayBest() {
        //1 查询缘分值最高的推荐用户
        RecommendUser recommendUser = recommendUserApi.todayBest(UserHolder.getUserId());

        //2 查询推荐给我的用户的详情数据
        UserInfo userInfo = userInfoApi.findById(recommendUser.getUserId());

        //3 构建vo对象
        TodayBest vo = TodayBest.init(userInfo, recommendUser);

        //4 返回数据
        return vo;
    }


    public static void main(String[] args) throws Exception {
        int count = 10 * 10000 * 10000;

        long now = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            User user1 = User.class.newInstance();
        }
        System.out.println("反射：" + (System.currentTimeMillis() - now));


        now = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            User user = new User();
        }
        System.out.println("new：" + (System.currentTimeMillis() - now));
    }

    //分页查询推荐好友
    public PageResult recommendation(RecommendUserDto dto) {
        //1 查询所有的推荐好友数据
        List<RecommendUser> recommendUserList = recommendUserApi.findByUserId(UserHolder.getUserId());

        //判断查询结果是否为空，如果为空，不需要往下走了
        if (recommendUserList == null || recommendUserList.isEmpty()) {
            return new PageResult(dto.getPage(), dto.getPagesize(), 0, null);
        }

        //获取推荐好友的ids
        //List<Long> ids = new ArrayList<>();
        //for (RecommendUser recommendUser : recommendUserList) {
        //    ids.add(recommendUser.getUserId());
        //}
        List<Long> ids = recommendUserList.stream().map(RecommendUser::getUserId)
                .collect(Collectors.toList());

        //2 根据 推荐好友id 和  查询条件  分页   查询用户详情 UserInfo
        Page<UserInfo> pages = userInfoApi.findByDto(ids, dto);
        List<UserInfo> userInfoList = pages.getRecords();
        //使用流的方式，把list转为map
        //其中   key为UserInfo的id(用户id)
        //      value是 UserInfo本身
        Map<Long, UserInfo> map = userInfoList.stream()
                //               toMap:转Map      key             value
                .collect(Collectors.toMap(UserInfo::getId, Function.identity()));

        //3 构建vos
        List<TodayBest> vos = new ArrayList<>();
        for (RecommendUser recommendUser : recommendUserList) {
            UserInfo userInfo = map.get(recommendUser.getUserId());
            if (userInfo != null) {
                TodayBest vo = TodayBest.init(userInfo, recommendUser);
                vos.add(vo);
            }
        }

        //4 返回分页对象
        return new PageResult(dto.getPage(), dto.getPagesize(), (int) pages.getTotal(), vos);
    }

    //根据用户id查询  佳人详情
    public TodayBest personalInfo(Long userId) {
        //1. 根据用户id查询用户详情
        UserInfo userInfo = userInfoApi.findById(userId);

        //2. 根据用户id和当前操作用户的id，查询推荐用户信息   获取评分数据
        RecommendUser recommendUser = recommendUserApi.find(userId, UserHolder.getUserId());

        //3. 构建vo对象
        TodayBest vo = TodayBest.init(userInfo, recommendUser);

        //记录访客信息
        Visitors visitors = new Visitors();
        visitors.setUserId(userId);
        visitors.setVisitorUserId(UserHolder.getUserId());
        visitors.setFrom("首页");
        visitors.setDate(System.currentTimeMillis());
        visitors.setVisitDate(DateUtil.format(new Date(), "yyyyMMdd"));
        visitorsApi.save(visitors);

        //4. 返回vo数据
        return vo;
    }

    //查看陌生人问题
    public String strangerQuestions(Long userId) {
        //1 根据用户id查询陌生人问题
        Question question = questionApi.findById(userId);

        //2 判断陌生人问题是否为空，为空指定默认问题
        String text = question == null ? "你的月收入多少？" : question.getTxt();

        //3 返回结果
        return text;
    }

    //回复陌生人问题
    public void replyQuestions(Long userId, String reply) {
        //1. 根据用户id查询用户详情
        UserInfo userinfo = userInfoApi.findById(UserHolder.getUserId());

        //2. 根据消息格式的要求，封装消息数据
        Map map = new HashMap();
        map.put("userId", UserHolder.getUserId());
        map.put("huanXinId", Constants.HX_USER_PREFIX + UserHolder.getUserId());
        map.put("nickname", userinfo.getNickname());
        map.put("strangerQuestion", strangerQuestions(userId));
        map.put("reply", reply);

        String json = JSON.toJSONString(map);

        //3. 发送消息
        huanXinTemplate.sendMsg(Constants.HX_USER_PREFIX + userId, json);
    }

    @Value("${tanhua.default.recommend.users}")
    private List<Long> userIds;

    //探花左滑右滑 数据查询
    public List<TodayBest> queryCardsList() {
        //1  查询推荐好友   随机获取10个推荐好友
        List<RecommendUser> recommendUserList = recommendUserApi.queryCardsList(UserHolder.getUserId());

        //2 判断是否查询到数据，
        if (CollUtil.isEmpty(recommendUserList)) {
            recommendUserList = new ArrayList<>();
            // 如果没有查询到，使用默认的推荐用户
            for (Long userId : userIds) {
                RecommendUser recommendUser = new RecommendUser();
                recommendUser.setUserId(userId);
                recommendUser.setToUserId(UserHolder.getUserId());
                recommendUser.setScore(RandomUtil.randomDouble(60, 90));
                recommendUserList.add(recommendUser);
            }
        }

        //3 根据推荐用户的ids查询用户的详情  userInfo
        List<Long> ids = recommendUserList.stream()
                .map(RecommendUser::getUserId).collect(Collectors.toList());
        Map<Long, UserInfo> map = userInfoApi.findByIds(ids).stream()
                .collect(Collectors.toMap(UserInfo::getId, Function.identity()));

        //4 封装vos
        List<TodayBest> vos = new ArrayList<>();
        for (RecommendUser recommendUser : recommendUserList) {
            UserInfo userInfo = map.get(recommendUser.getUserId());
            if (userInfo != null) {
                TodayBest vo = TodayBest.init(userInfo, recommendUser);
                vos.add(vo);
            }
        }

        //返回数据
        return vos;
    }

    //喜欢
    public void likeUser(Long likeUserId) {
        //1 保存喜欢数据
        boolean save = userLikeApi.save(UserHolder.getUserId(), likeUserId, true);

        //如果保存数据失败，抛异常
        if (!save) {
            throw new RuntimeException("保存喜欢数据失败");
        }

        //2 保存redis的缓存
        //添加喜欢set数据
        redisTemplate.opsForSet().add(Constants.USER_LIKE_KEY + UserHolder.getUserId(), likeUserId.toString());
        //删除不喜欢的set数据
        redisTemplate.opsForSet().remove(Constants.USER_NOT_LIKE_KEY + UserHolder.getUserId(), likeUserId.toString());

        //3 是否是双向喜欢，如果是双向喜欢，加好友
        Boolean member = redisTemplate.opsForSet().isMember(Constants.USER_LIKE_KEY + likeUserId, UserHolder.getUserId().toString());
        if (member) {
            friendApi.save(UserHolder.getUserId(), likeUserId);
        }
    }

    //不喜欢
    public void notLikeUser(Long likeUserId) {
        //1 保存不喜欢数据
        boolean save = userLikeApi.save(UserHolder.getUserId(), likeUserId, false);

        //如果保存数据失败，抛异常
        if (!save) {
            throw new RuntimeException("保存不喜欢数据失败");
        }

        //2 保存redis的缓存
        //添加不喜欢set数据
        redisTemplate.opsForSet().add(Constants.USER_NOT_LIKE_KEY + UserHolder.getUserId(), likeUserId.toString());
        //删除喜欢的set数据
        redisTemplate.opsForSet().remove(Constants.USER_LIKE_KEY + UserHolder.getUserId(), likeUserId.toString());

        //3 是否是双向不喜欢，如果是双向不喜欢，删除好友（双向）
        //TODO 学员完成
    }

    //搜附近
    public List<NearUserVo> queryNearUser(String gender, String distance) {
        //1 搜索当前操作用户，指定距离的附近的人
        List<Long> ids = userLocationApi.queryNearUser(UserHolder.getUserId(), Double.parseDouble(distance));

        //2 判断结果是否为空，为空直接返回
        if (CollUtil.isEmpty(ids)) {
            return null;
        }

        //3 根据附近的人的ids查询用户详情，根据性别进行查询
        List<UserInfo> userInfoList = userInfoApi.findByIds(ids, gender);

        //4 封装vos
        List<NearUserVo> vos = new ArrayList<>();
        for (UserInfo userInfo : userInfoList) {
            //排除我自己
            if (userInfo.getId() == UserHolder.getUserId()) {
                continue;
            }

            NearUserVo vo = NearUserVo.init(userInfo);
            vos.add(vo);
        }

        //5 返回数据
        return vos;
    }
}
